package io.p2p.stream.p2pmain.session;

import io.p2p.stream.p2pmain.node.ActiveNode;
import io.p2p.stream.p2pmain.task.ActiveNodeHeartbeatMonitorTask;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 会话管理单例类
 */
public class ActiveNodeSessionManager {
    private static ActiveNodeSessionManager instance;

    private ActiveNodeSessionManager(){
        // 使用ScheduledExecutorService执行心跳检测任务
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        scheduler.scheduleAtFixedRate(new ActiveNodeHeartbeatMonitorTask(activeNodeMap), 0, 10, TimeUnit.SECONDS); // 每10秒执行一次
    }

    public static ActiveNodeSessionManager getInstance(){
        if(instance == null){
            synchronized (ActiveNodeSessionManager.class){
                if(instance == null) {
                    instance = new ActiveNodeSessionManager();
                }
            }
        }
        return instance;
    }

    private Map<String, ActiveNode> activeNodeMap = new ConcurrentHashMap<>();

    public Map<String,ActiveNode> getActiveNodeMap(){
        Map<String,ActiveNode> deepCopyMap = new HashMap<>();
        activeNodeMap.forEach(deepCopyMap::put);
        return deepCopyMap;
    }

    public void pushBack(String key,ActiveNode node){
        activeNodeMap.put(key,node);
    }

    public void remove(String ip,int port){
        Iterator<ActiveNode> it = activeNodeMap.values().iterator();
        while(it.hasNext()){
            ActiveNode node = it.next();
            if(node.getIp().equals(ip) && node.getPort() == port){
                it.remove();
                break;
            }
        }
    }

    public ActiveNode find(String name){
        return activeNodeMap.get(name);
    }

    public ActiveNode flush(String name,int natType){
        synchronized (activeNodeMap) {
            ActiveNode node = activeNodeMap.get(name);
            if (node != null) {
                node.setNatType(natType);
            }
            return node;
        }
    }

    public ActiveNode flush(String name, String remoteIP,int remotePort){
        synchronized (activeNodeMap) {
            ActiveNode node = activeNodeMap.get(name);
            if (node != null) {
                node.setLastActiveTime(new Date());
            } else {
                ActiveNode newNode = new ActiveNode();
                newNode.setName(name);
                newNode.setIp(remoteIP);
                newNode.setPort(remotePort);
                newNode.setLastActiveTime(new Date());
                activeNodeMap.put(name, newNode);
                node = newNode;
            }
            return node;
        }
    }


}
